#include <iostream>
#include <map>
#include <string>
#include <vector>
#include "IR.h"


class Scope;

class Symbol
{
    friend Scope;

public:
    sysy::Type *type;
    std::vector<int> dims;
    sysy::Value *value;
    bool isConst;
    bool isGlobal;
    std::string name;
    std::string reg_Name;

protected:
    Symbol(sysy::Type *type,
           //           const std::vector<int>&  dims,
           sysy::Value *value, bool isConst, bool isGlobal, const std::string &name, const std::string &reg_name) :
        type(type), value(value), isConst(isConst), isGlobal(isGlobal), name(name), reg_Name(reg_name)
    {
    }
};

class Scope
{
public:
    using symbol_table_t = std::map<std::string, std::unique_ptr<Symbol>>;
    std::vector<symbol_table_t> tables;

public:
    Scope() : preEnter(false) { tables.emplace_back(); }

    bool preEnter;

    void pushLayer()
    {
        if (preEnter)
        {
            preEnter = false;
            return;
        }
        tables.emplace_back();
    }

    symbol_table_t &top() { return tables[tables.size() - 1]; }

    void popLayer() { tables.pop_back(); }

    bool isGlobal() { return tables.size() == 1; }

    Symbol *find(const std::string &name)
    {
        for (auto i = tables.rbegin(); i != tables.rend(); i++)
        {
            if (auto res = i->find(name); res != i->end())
            {
                return res->second.get();
            }
        }
        return nullptr;
    }

    void insert(sysy::Type *type, sysy::Value *value, bool isConst, const std::string &name, const std::string reg_Name)
    {
        auto &currentScope = top();
        if (currentScope.find(name) != currentScope.end())
        {
            // 抛出异常? 还是想办法报重定义错误
            std::cerr << "Error: 变量" << name << "重定义.\n";
            exit(-1);
        }
        assert(currentScope.emplace(name, new Symbol(type, value, isConst, isGlobal(), name, reg_Name)).second);
    }
};
